home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / QuickTime / JPEG Sample / Source / displays.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-05  |  10.8 KB  |  422 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2. #
  3. #        displays.c
  4. #
  5. #        This segment handles the Display Manager notification and
  6. #        repositions application windows in response.
  7. #
  8. #        Author(s):     Michael Marinkovich
  9. #                    marink@apple.com
  10. #
  11. #        Modification History: 
  12. #
  13. #            10/12/95    MWM     Initial coding                     
  14. #            10/05/96    MWM        Removed the fixed window title bar height and
  15. #                                replaced it with a func that calculates the
  16. #                                proper height.
  17. #
  18. #
  19. #        Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
  20. #
  21. #
  22. #        You may incorporate this sample code into your applications without
  23. #        restriction, though the sample code has been provided "AS IS" and the
  24. #        responsibility for its operation is 100% yours.  However, what you are
  25. #        not permitted to do is to redistribute the source as "DSC Sample Code"
  26. #        after having made changes. If you're going to re-distribute the source,
  27. #        we require that you make it clear in the source that the code was
  28. #        descended from Apple Sample Code, but that you've made changes.
  29. #
  30. *************************************************************************************/
  31.  
  32. #include <Events.h>
  33. #include <ToolUtils.h>
  34. #include <Gestalt.h>
  35. #include <LowMem.h>
  36. #include <OSUtils.h>
  37. #include <QuickDraw.h>
  38.  
  39. #include "App.h"
  40. #include "Proto.h"
  41.  
  42.  
  43. //----------------------------------------------------------------------
  44. //
  45. //    InstallAEDMNotification - tell DM that we want to be notified by AE.
  46. //                      
  47. //                      
  48. //----------------------------------------------------------------------
  49.  
  50. OSErr InstallAEDMNotification(void)
  51. {
  52.     OSErr            err = noErr;
  53.     
  54.     err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
  55.                                 NewAEEventHandlerProc(WorldChangedProc),
  56.                                 0L, false);
  57.     return err;
  58.  
  59. }
  60.  
  61.  
  62.  
  63. //----------------------------------------------------------------------
  64. //
  65. //    WorldChangedProc - Display Manager calls this proc when a depth or  
  66. //                       mode change is made. Your application should
  67. //                       handle window repositioning here. 
  68. //----------------------------------------------------------------------
  69.  
  70. pascal OSErr WorldChangedProc(AppleEvent event, AppleEvent reply, long refCon)
  71. {
  72.     #pragma unused (refCon)
  73.     OSErr            err = noErr;
  74.  
  75.     err = HandleNotification(&event);
  76.     
  77.     return noErr;
  78.     
  79. }
  80.  
  81.  
  82. //----------------------------------------------------------------------
  83. //
  84. //    HandleNotification - handle the AppleEvent returned by the 
  85. //                           AppleEvent procedure.
  86. //                      
  87. //----------------------------------------------------------------------
  88.  
  89. OSErr HandleNotification(AppleEvent *event)
  90. {
  91.     OSErr                    err = noErr;
  92.     GrafPtr                    oldPort;
  93.     AEDescList                displayList;
  94.     AEDescList                aDisplay;
  95.     AERecord                oldConfig,newConfig;
  96.     AEKeyword                tempWord;
  97.     DisplayIDType            displayID;
  98.     unsigned long            returnType;
  99.     long                    count;
  100.     Rect                    oldRect, newRect;
  101.     
  102.     GetPort(&oldPort);
  103.  
  104.     // Get a list of the displays from the Display Notice AppleEvent.
  105.     err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
  106.     // How many items in the list
  107.     err = AECountItems(&displayList,&count);
  108.     
  109.     while (count > 0)          // Loop through the list.
  110.     {
  111.         err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, 
  112.                                     &aDisplay);
  113.         
  114.         // Get the Old Rect.            
  115.         err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord, 
  116.                            &oldConfig);
  117.         err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard, 
  118.                           &returnType, &oldRect, 8, nil);
  119.         
  120.         // Get the DisplayID so we can get the GDevice later.                
  121.         err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard, 
  122.                           &returnType, &displayID, 8, nil);
  123.  
  124.         // Get the New Rect.                
  125.         err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, 
  126.                            &newConfig);
  127.         err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard, 
  128.                           &returnType, &newRect, 8, nil);
  129.         
  130.         // If the New and Old rects are not the same then we can assume
  131.         // the GDevice has changed and we need to rearrange the windows.
  132.         if (err == noErr && !EqualRect(&newRect, &oldRect))
  133.             HandleDeviceChange(displayID, &newRect);
  134.  
  135.         count--;
  136.         err = AEDisposeDesc(&aDisplay);
  137.         err = AEDisposeDesc(&oldConfig);
  138.         err = AEDisposeDesc(&newConfig);
  139.  
  140.     }
  141.     
  142.     err = AEDisposeDesc(&displayList);
  143.     SetPort(oldPort);
  144.     
  145.     return err;
  146.     
  147. }
  148.  
  149.  
  150. //----------------------------------------------------------------------
  151. //
  152. //    HandleDeviceChange - called when the oldconfig is different from 
  153. //                         newconfig. Will check all windows on effected 
  154. //                           device and move if needed.
  155. //----------------------------------------------------------------------
  156.  
  157. OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
  158. {
  159.     OSErr            err;
  160.     GDHandle        gd;
  161.     GDHandle        onGD;
  162.     WindowRef        window;
  163.     
  164.     // Get the GDevice from the DisplayID.
  165.     err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
  166.  
  167.     if (err == noErr && gd != nil) 
  168.     {
  169.         window = LMGetWindowList();
  170.         
  171.         while (nil != window) 
  172.         {
  173.             SetPort(window); 
  174.             // which device holds the greatest portion of the window
  175.             onGD = GetGreatestDevice(window);
  176.             
  177.             // If the window is not 50% or greater on
  178.             // the desired device then pass it up.
  179.             if (onGD == gd) 
  180.             { 
  181.                 if (OutOfBoundsRect(window->portRect, *newRect)) 
  182.                 {
  183.                     MoveInbounds(window, gd, *newRect); 
  184.                     if (OutOfBoundsRect(window->portRect, *newRect)) 
  185.                     {
  186.                         ResizeInbounds(window, gd, *newRect);
  187.                         
  188.                         // If it is one of our document windows then we need
  189.                         // to reset the std state and the scroll bars.
  190.                         if (GetIsAppWindow(window))
  191.                             AdjustScrollbars(window, true);
  192.                     }        
  193.                 }
  194.                 ResetStdState(window);
  195.  
  196.             }    
  197.             window = (WindowRef)(((WindowPeek)window)->nextWindow);
  198.         }
  199.     }
  200.     
  201.     return err;
  202.     
  203. }
  204.  
  205.     
  206. //----------------------------------------------------------------------
  207. //
  208. //    OutOfBoundsRect -  check to see if the window is out of the device
  209. //                       rect.
  210. //                      
  211. //----------------------------------------------------------------------
  212.  
  213. Boolean OutOfBoundsRect(Rect windRect, Rect screenRect)
  214. {
  215.     Boolean        out = false;
  216.     
  217.  
  218.     GlobalToLocal(&TopLeft(screenRect));
  219.     GlobalToLocal(&BotRight(screenRect));
  220.         
  221.     if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
  222.         out = true;
  223.  
  224.     if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top))
  225.         out = true;
  226.         
  227.     return out;
  228.     
  229. }
  230.     
  231.     
  232. //----------------------------------------------------------------------
  233. //
  234. //    MoveInbounds -  Move window on to desired device
  235. //                        
  236. //                      
  237. //----------------------------------------------------------------------
  238.  
  239. void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  240. {
  241.     Rect        bounds;
  242.     short        hGlobal;
  243.     short        vGlobal;
  244.     
  245.     bounds = window->portRect;
  246.     
  247.     LocalToGlobal(&TopLeft(bounds));
  248.     LocalToGlobal(&BotRight(bounds));
  249.     
  250.     hGlobal = bounds.left;
  251.     vGlobal = bounds.top;
  252.     
  253.     // we want to make the left top a priority so adjust it first
  254.     // as to override the bottom, right movements. This is so we
  255.     // can resize the window later. No need to adjust the top 
  256.     // because the top coordinates don't change.
  257.     
  258.     if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
  259.         ((bounds.bottom - bounds.top) > (screenRect.bottom - screenRect.top))) 
  260.     {
  261.         
  262.         // adjust left
  263.         if (bounds.left < screenRect.left)
  264.             hGlobal = screenRect.left + 4;
  265.         
  266.         vGlobal = screenRect.top;
  267.         if (gd == GetMainDevice())
  268.             vGlobal += (GetMBarHeight() + GetWTitleHeight(window));
  269.  
  270.     }    
  271.     else 
  272.     {
  273.         // adjust left
  274.         if (bounds.left < screenRect.left)
  275.             hGlobal = screenRect.left + 4;
  276.  
  277.         if ((bounds.top - 100 < screenRect.top) && (gd == GetMainDevice()))
  278.             vGlobal = screenRect.top + (GetMBarHeight() + GetWTitleHeight(window));
  279.  
  280.         // adjust right
  281.         if (bounds.right > screenRect.right)
  282.             hGlobal = (screenRect.right - (bounds.right - bounds.left)) - 4;
  283.         
  284.         // adjust bottom
  285.         if (bounds.bottom > screenRect.bottom)
  286.             vGlobal = (screenRect.bottom - (bounds.bottom - bounds.top)) - 4;
  287.     }
  288.     
  289.     MoveWindow(window, hGlobal, vGlobal,false);
  290.         
  291. }
  292.     
  293.  
  294. //----------------------------------------------------------------------
  295. //
  296. //    ResizeInbounds -  resize the window to fit in the graphics device
  297. //                        
  298. //                      
  299. //----------------------------------------------------------------------
  300.  
  301. void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  302. {
  303.     Rect        windRect;
  304.     short        h;
  305.     short        v;
  306.  
  307.     windRect = window->portRect;
  308.     
  309.     // make the window bounds the size of the gdRect
  310.     // less the fudge factor.
  311.     h = windRect.right - windRect.left;
  312.     v = windRect.bottom - windRect.top;
  313.  
  314.     if (h > screenRect.right - screenRect.left)
  315.         h = (screenRect.right - screenRect.left) - 8;
  316.     
  317.     if (v > screenRect.bottom - screenRect.top) 
  318.     {
  319.         v = (screenRect.bottom - screenRect.top) - 8;
  320.         
  321.         // If we are on the main device then subtract the mBar
  322.         // height. Also subtract the height of the title
  323.         // bar on the window. 
  324.         
  325.         if (gd == GetMainDevice())
  326.             v -= (LMGetMBarHeight() + GetWTitleHeight(window));
  327.     }        
  328.  
  329.         
  330.     SizeWindow(window, h, v, true);
  331.  
  332. }
  333.     
  334.  
  335. //----------------------------------------------------------------------
  336. //
  337. //    GetGreatestDevice - find thw device that holds the greatest area 
  338. //                        of the window.
  339. //                      
  340. //----------------------------------------------------------------------
  341.  
  342. GDHandle GetGreatestDevice(WindowRef window)
  343. {
  344.     GDHandle    gd;
  345.     GDHandle    savedGD;
  346.     Rect        gdRect;
  347.     Rect        foundRect;
  348.     long        size;
  349.     long        greatest = nil;
  350.  
  351.     gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
  352.     savedGD = gd;
  353.     
  354.     // Loop through the device list
  355.     while (gd != nil) 
  356.     {    
  357.         gdRect = (**gd).gdRect;
  358.         
  359.         GlobalToLocal(&TopLeft(gdRect));
  360.         GlobalToLocal(&BotRight(gdRect));
  361.         
  362.         if (SectRect(&window->portRect, &gdRect, &foundRect)) 
  363.         {
  364.             size = ((long)(foundRect.right - foundRect.left) * 
  365.                    (long)(foundRect.bottom - foundRect.top));
  366.             
  367.             if (size > greatest) 
  368.             {
  369.                 greatest = size;
  370.                 savedGD = gd;        // save the greatest device
  371.             }    
  372.         }
  373.         gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
  374.     }
  375.     
  376.     return savedGD;
  377.     
  378. }
  379.  
  380.  
  381. //----------------------------------------------------------------------
  382. //
  383. //    ResetStdState - since we are now on a different size screen we need
  384. //                    to change the stdState window size so our zooming
  385. //                    will work properly.  
  386. //----------------------------------------------------------------------
  387.  
  388. void ResetStdState(WindowRef window)
  389. {
  390.     Rect        screenRect;
  391.     
  392.     screenRect = window->portRect;
  393.  
  394.     LocalToGlobal(&TopLeft(screenRect));
  395.     LocalToGlobal(&BotRight(screenRect));
  396.     
  397.     SetWindowStandardState(window, &screenRect);
  398.     
  399. }
  400.     
  401.     
  402. //----------------------------------------------------------------------
  403. //
  404. //    GetWTitleHeight - return the height of the titlebar for a given
  405. //                      window. If the window is nil a zero height will
  406. //                        be returned.
  407. //----------------------------------------------------------------------
  408.     
  409. short GetWTitleHeight(WindowRef window)
  410. {
  411.     short            tHeight = 0;
  412.     
  413.     if (nil != window)                
  414.         tHeight = (**((WindowPeek)window)->contRgn).rgnBBox.top - 
  415.                      (**((WindowPeek)window)->strucRgn).rgnBBox.top;
  416.     
  417.     return tHeight;
  418.  
  419. }
  420.     
  421.  
  422.